package com.emapp.lccode.fragment

import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Point
import android.graphics.drawable.Drawable
import android.location.Location
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.view.View
import android.widget.TextView
import androidx.lifecycle.viewModelScope
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.customview.getCustomView
import com.afollestad.materialdialogs.lifecycle.lifecycleOwner
import com.amap.api.maps.AMap
import com.amap.api.maps.AMap.OnMarkerClickListener
import com.amap.api.maps.AMap.OnMyLocationChangeListener
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.MapFragment
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.CameraPosition
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.MarkerOptions
import com.amap.api.maps.model.Polyline
import com.amap.api.maps.model.PolylineOptions
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
import com.emapp.lccode.R
import com.emapp.lccode.activity.DeviceAddKtActivity
import com.emapp.lccode.activity.ReportKtActivity
import com.emapp.lccode.base.BaseApplication
import com.emapp.lccode.base.BaseConfig
import com.emapp.lccode.base.BaseConfig.nais
import com.emapp.lccode.base.BaseFragment1
import com.emapp.lccode.base.EventBusConfig
import com.emapp.lccode.base.EventBusModel
import com.emapp.lccode.bean.DeviceKt
import com.emapp.lccode.bean.SelectType
import com.emapp.lccode.bean.UpLatLngKt
import com.emapp.lccode.databinding.FragmentMapsBinding
import com.emapp.lccode.mode.MapViewModel
import com.emapp.lccode.utils.BaseUtil
import com.emapp.lccode.utils.MapAppUtil
import com.emapp.lccode.utils.MmkvUtil
import com.emapp.lccode.utils.SettingUtil.isLocationEnabled
import com.emapp.lccode.utils.getIconByName
import com.emapp.lccode.utils.getIconByNameState
import com.emapp.lccode.utils.getLuByNameState
import com.emapp.lccode.utils.scaleBitmap
import com.emapp.lccode.utils.showMessage
import com.emapp.lccode.utils.toJsonStr
import com.emapp.lccode.utils.toStartActivity
import com.emapp.lccode.utils.years
import com.emapp.lccode.view.DistrictDialog
import com.emapp.lccode.view.MapDeviceTypeDialog
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import com.hjq.toast.Toaster
import com.mylhyl.circledialog.CircleDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.invoke
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.hgj.jetpackmvvm.ext.parseState
import me.hgj.jetpackmvvm.ext.util.setOnclickNoRepeat
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import com.bumptech.glide.request.target.Target

class MapKtFragment : BaseFragment1<MapViewModel, FragmentMapsBinding>(),
    OnMyLocationChangeListener, OnMarkerClickListener, MapDeviceTypeDialog.SelectTypeListener,
    DistrictDialog.SelectDistrictListener, AMap.OnPolylineClickListener,
    AMap.OnCameraChangeListener {
    var mapDatas: ArrayList<DeviceKt> = arrayListOf()
    private lateinit var handler: Handler
    private var runnable: Runnable? = null
    private val delayMillis = 1000L // 延迟1秒的毫秒数
    override fun initView(savedInstanceState: Bundle?) {
        mViewBind.lvTitle.ivLeft.visibility = View.GONE
        mViewBind.lvTitle.tvTitle.text = "巡检"
        EventBus.getDefault().register(this)
        handler = Handler(Looper.getMainLooper())
        if (!BaseApplication.instance.getUser()?.area_city.isNullOrBlank()) {
            mViewBind.tvDistrict.text =
                BaseApplication.instance.getUser()?.area_city?.substringAfterLast("/")
        }
        if (!isLocationEnabled(requireActivity())) {
            showMessage(
                "手机定位服务未打开！",
                "温馨提示",
                "去开启",
                positiveAction = {
                    val settingsIntent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
                    startActivity(settingsIntent)
                })
        }
        getPermission()
    }

    /**
     * 懒加载
     */
    override fun lazyLoadData() {

    }


    override fun createObserver() {
        mViewModel.run {
            orders.observe(viewLifecycleOwner) { resultState ->
                parseState(resultState, {
                    if (it.data != null && it.data.size > 0) {
                        mViewBind.lvCheck.visibility = View.VISIBLE
                        checkId = it.data[0].id
                        mViewBind.ivStart.visibility = View.GONE
                    } else {
                        mViewBind.lvCheck.visibility = View.GONE
                        mViewBind.ivStart.visibility = View.VISIBLE
                        checkId = ""
                    }
                }, {
                    Toaster.show(it.errorMsg)
                })
            }
            check_id.observe(viewLifecycleOwner) { result ->
                log_e("result: $result")
                if (result == "1" || result.isEmpty()) {
                    checkId = ""
                    mViewBind.lvCheck.visibility = View.GONE
                    mViewBind.ivStart.visibility = View.VISIBLE
                } else if (result == "0") {
                    mViewBind.lvCheck.visibility = View.VISIBLE
                    mViewBind.ivStart.visibility = View.GONE
                } else {
                    checkId = result
                    mViewBind.lvCheck.visibility = View.VISIBLE
                    mViewBind.ivStart.visibility = View.GONE
                }
                upLatLngs.subList(0, upLatLngs.size - 1).clear()
            }
            device.observe(viewLifecycleOwner) { resultState ->
                dismissLoading()
                parseState(resultState, {
                    val newdata = it.subtract(mapDatas)
                    val deletedata = mapDatas.subtract(it)
                    mapDatas = it
                    removeMarker(deletedata)
                    if (newdata != null) {
                        viewModelScope.launch {
                            withContext(Dispatchers.IO) {
                                newdata.forEach { d ->
                                    if (!d.lat.isNullOrBlank() && !d.lng.isNullOrBlank() && d.lat?.toDoubleOrNull() != null && d.title?.isNotEmpty() == true) {
                                        addMarker(d)
                                    }
                                    if (d.lu != null) {
                                        d.lu!!.features?.forEach { features ->
                                            val geometry = features.geometry
                                            if (geometry != null) {
                                                val lat: ArrayList<LatLng> = arrayListOf()
                                                when (geometry.type) {
                                                    "LineString" -> {
                                                        lat.clear()
                                                        val data =
                                                            geometry.coordinates as? ArrayList<ArrayList<Double>>
                                                        data?.forEach { c ->
                                                            lat.add(
                                                                MapAppUtil.other2Gao(
                                                                    requireActivity(),
                                                                    LatLng(c[1], c[0])
                                                                )
                                                            )
                                                        }
                                                        addPolyline(lat, d)
                                                    }

                                                    "Polygon", "MultiLineString" -> {//
                                                        val data =
                                                            geometry.coordinates as? ArrayList<ArrayList<ArrayList<Double>>>
                                                        data?.forEach { c ->
                                                            lat.clear()
                                                            c.forEach { cc ->
                                                                lat.add(
                                                                    MapAppUtil.other2Gao(
                                                                        requireActivity(),
                                                                        LatLng(cc[1], cc[0])
                                                                    )
                                                                )
                                                            }
                                                            addPolyline(lat, d)
                                                        }
                                                    }

                                                    "MultiPolygon" -> {
                                                        val data =
                                                            geometry.coordinates as? ArrayList<ArrayList<ArrayList<ArrayList<Double>>>>
                                                        data?.forEach { c ->
                                                            c.forEach { cc ->
                                                                lat.clear()
                                                                cc.forEach { ccc ->
                                                                    lat.add(
                                                                        MapAppUtil.other2Gao(
                                                                            requireActivity(),
                                                                            LatLng(ccc[1], ccc[0])
                                                                        )
                                                                    )
                                                                }
                                                                addPolyline(lat, d)
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            dismissLoading()
                        }
                    }

                }, {
                    Toaster.show(it.errorMsg)
                })
            }
        }
    }


    /**
     * 绘制设备路线
     */
    @SuppressLint("CheckResult")
    suspend fun addMarker(device: DeviceKt) {
        val mark = MarkerOptions().anchor(0.5f, 1.0f)
            .snippet(device.title)
            .position(
                LatLng(
                    device.lat!!.toDouble(),
                    device.lng!!.toDouble()
                )
            )
        if (device.iconthumb.isNullOrEmpty() || device.iconthumb == "null" || device.iconthumb == "0") {
            val originalIconResId = getIconByName(device.work_type, device.title)
            var originalIconBitmap = BitmapFactory.decodeResource(resources, originalIconResId)
            if (device.daysSinceLastRun() < 8) {
                originalIconBitmap = createMarkerWithDot(originalIconBitmap, Color.GREEN) //
            }
            mark.icon(
                BitmapDescriptorFactory.fromBitmap(originalIconBitmap)
            )
            withContext(Dispatchers.Main) {
                mViewModel.markers.offer(mViewModel.aMap.addMarker(
                    mark
                ).apply { `object` = device })
            }
        } else {
            val url = if (device.iconthumb.startsWith("http")) device.iconthumb else BaseConfig.ROOT_URL + device.iconthumb
            Glide.with(this).asBitmap().load(url).override(60, 70)
                .into(object : CustomTarget<Bitmap>() {
                    override fun onResourceReady(
                        resource: Bitmap,
                        transition: Transition<in Bitmap>?,
                    ) {
                        var originalIconBitmap = resource
                        if (device.daysSinceLastRun() < 8) {
                            originalIconBitmap = createMarkerWithDot(originalIconBitmap) //
                        }
                        mark.icon(BitmapDescriptorFactory.fromBitmap(originalIconBitmap))
                        mViewModel.markers.offer(mViewModel.aMap.addMarker(
                            mark
                        ).apply { `object` = device })

                    }

                    override fun onLoadCleared(p0: Drawable?) {
                        // 图片清除时的回调，例如错误或加载前的占位图处理
                    }
                })
        }


    }

    private fun createMarkerWithDot(iconBitmap: Bitmap, dotColor: Int = Color.GREEN): Bitmap {
        val dotSize = 18 // 圆点的直径
        val output = Bitmap.createBitmap(iconBitmap.width, iconBitmap.height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(output)

        // 绘制原始图标
        canvas.drawBitmap(iconBitmap, 0f, 0f, null)

        // 创建画笔用于绘制圆点
        val paint = Paint(Paint.ANTI_ALIAS_FLAG)
        paint.color = dotColor
        paint.style = Paint.Style.FILL

        // 计算圆点的位置，例如放在图标底部中心
        val centerX = iconBitmap.width / 2f
        val centerY = iconBitmap.height - dotSize / 2f

        // 绘制圆点
        canvas.drawCircle(centerX, centerY, dotSize / 2f, paint)

        return output
    }

    private suspend fun addPolyline(lat: ArrayList<LatLng>, device: DeviceKt) {
        var draw = R.drawable.map_l_guan
        draw = getLuByNameState(
            device.work_type,
            device.title,
            device.build_status
        )
        val poly = PolylineOptions()
            .addAll(lat)
            .width(10f)
            .setCustomTexture(BitmapDescriptorFactory.fromResource(draw))
//        Glide.with(this).asBitmap().load(device.iconthumb)
//            .into(object : SimpleTarget<Bitmap>() {
//                override fun onResourceReady(
//                    resource: Bitmap,
//                    transition: Transition<in Bitmap>?,
//                ) {
////                    var originalIconBitmap = resource
////                    if (device.daysSinceLastRun() < 8) {
////                        originalIconBitmap = createMarkerWithDot(originalIconBitmap, Color.GREEN) //
////                    }
//                    poly.setCustomTexture(BitmapDescriptorFactory.fromBitmap(resource))
//                    val l = (mViewModel.aMap).addPolyline(
//                        poly
//                    ).apply { mViewModel.polylineDataMap[id] = device }
//                    mViewModel.lines.offer(l)
//                }
//            })

        withContext(Dispatchers.Main) {
            val l = (mViewModel.aMap).addPolyline(
                poly
            ).apply { mViewModel.polylineDataMap[id] = device }
            mViewModel.lines.offer(l)
        }
    }

    private fun getPermission() {
        XXPermissions.with(this)
            .permission(Permission.ACCESS_COARSE_LOCATION)
            .permission(Permission.ACCESS_FINE_LOCATION)
            .permission(Permission.READ_PHONE_STATE)
            .request(object : OnPermissionCallback {
                override fun onGranted(permissions: List<String>, all: Boolean) {
                    MmkvUtil.putBoolean("loc_permission", true)
                    setUpMapIfNeeded()
                    getPoint()
                    // getDevice()

                }

                override fun onDenied(permissions: List<String>, never: Boolean) {}
            })
    }

    private fun setUpMapIfNeeded() {
        mViewModel.aMap =
            (requireActivity().fragmentManager.findFragmentById(R.id.map) as MapFragment).map.apply {
                isMyLocationEnabled = true
                setOnMyLocationChangeListener(this@MapKtFragment)
                setOnCameraChangeListener(this@MapKtFragment)
                moveCamera(CameraUpdateFactory.zoomTo(15f))
                uiSettings.isZoomControlsEnabled = false
                uiSettings.isRotateGesturesEnabled = false
                uiSettings.isMyLocationButtonEnabled = false // 设置默认定位按钮是否显示
                setOnMarkerClickListener(this@MapKtFragment)
                setOnPolylineClickListener(this@MapKtFragment)
                myLocationStyle = MapAppUtil.setupLocationStyle(10)
                minZoomLevel = 12f
            }
    }

    override fun onBindViewClick() {
        setOnclickNoRepeat(
            mViewBind.ivStart, mViewBind.tvEnd, mViewBind.tvUp,
            mViewBind.tvYear, mViewBind.tvDistrict, mViewBind.tvType, mViewBind.ivLoc
        ) {
            when (it.id) {
                R.id.iv_start -> {
                    //CheckDialog.create().show(getActivity());
                    if (mViewModel.upLatLngs.size == 0) {
                        Toaster.show("还未获取到新的定位数据,请稍等")
                        return@setOnclickNoRepeat
                    }
//                    val upLatLng: UpLatLngKt = upLatLngs[upLatLngs.size - 1]
//                    upLatLngs.clear()
//                    upLatLngs.add(upLatLng)
                    mViewModel.upLatLngs.subList(0, mViewModel.upLatLngs.size - 1).clear()
                    val s = mViewModel.upLatLngs.toJsonStr()
                    showLoading()
                    mViewModel.addMap("", "0", "", "1", s)

                }

                R.id.tv_end -> {
                    val s2 = mViewModel.upLatLngs.toJsonStr()
                    showLoading()
                    mViewModel.addMap("", "0", mViewModel.checkId, "3", s2)
                }

                R.id.tv_up -> {
                    toStartActivity(ReportKtActivity::class.java)
                }

                R.id.tv_year -> {
                    CircleDialog.Builder()
                        .setItems(years) { _, position ->
                            mViewBind.tvYear.text =
                                if (years[position] == "全部") "年份" else years[position]
                            mViewModel.year = if (years[position] == "全部") "" else years[position]
                            getDevice()
                            true
                        }
                        .setNegative("取消", null)
                        .show(parentFragmentManager)
                }

                R.id.tv_district -> {
                    mViewModel.districtDialog.listener = this
                    mViewModel.districtDialog.selectType = mViewModel.selectDistrict
                    mViewModel.districtDialog.show(requireActivity())
                }

                R.id.tv_type -> {
                    mViewModel.typeDialog.listener = this
                    mViewModel.typeDialog.work_type1 = mViewModel.work_type
                    mViewModel.typeDialog.device_type1 = mViewModel.device_type
                    mViewModel.typeDialog.show(requireActivity())
                }

                R.id.iv_loc -> {
                    if (mylocation != null && mylocation!!.latitude > 0) {
                        mViewModel.aMap.moveCamera(
                            CameraUpdateFactory.newLatLngZoom(
                                LatLng(
                                    mylocation!!.latitude,
                                    mylocation!!.longitude
                                ), 15f
                            )
                        )
                    }
                }
            }
        }
    }

    private fun getDevice() {
        //  mViewModel.getDevice(mViewModel.work_type, mViewModel.device_type, mViewModel.year, mViewModel.city, mViewModel.district)
        mViewModel.getDevice()

    }

    private var mylocation: Location? = null
    override fun onMyLocationChange(location: Location?) {
        if (location == null) {
            Toaster.show("定位失败，请检查您的定位权限")
            return
        }
        if (location.latitude == 0.0)
            return
        mylocation = location
        if (location.latitude > 0) {
            mViewModel.upLatLngs.add(UpLatLngKt(location.longitude, location.latitude))
            if (mViewModel.upLatLngs.size > 20) {
                mViewModel.upLatLngs.removeAt(0)
            }
        }
        if (mViewModel.isFirstLoc && location.latitude > 0) {
            mViewModel.aMap.moveCamera(
                CameraUpdateFactory.newLatLng(
                    LatLng(
                        location.latitude,
                        location.longitude
                    )
                )
            )
            mViewModel.isFirstLoc = false
            mViewModel.getTrackMapList("", "0", "", 0)
        }

    }

    override fun onMarkerClick(p0: Marker?): Boolean {
        val device: DeviceKt = p0?.`object` as DeviceKt
        if (device != null)
            showInfo(device)
        return true
    }

    override fun onPolylineClick(p0: Polyline?) {
        val device: DeviceKt? = mViewModel.polylineDataMap[p0?.id]
        if (device != null)
            showInfo(device)
    }

    @SuppressLint("SetTextI18n")
    private fun showInfo(device: DeviceKt) {
        MaterialDialog(requireContext()).show {
            lifecycleOwner(viewLifecycleOwner)
            customView(R.layout.dialog_map_device)
            val name = getCustomView().findViewById<TextView>(R.id.tv_name)
            val content = getCustomView().findViewById<TextView>(R.id.tv_content)
            val edit = getCustomView().findViewById<TextView>(R.id.tv_edit)
            val add = getCustomView().findViewById<TextView>(R.id.tv_add)
            val go = getCustomView().findViewById<TextView>(R.id.tv_go)
            name.text = device.title ?: ""
            content.text = (device.name
                ?: "无名") + "\n状态：${if (device?.device_status == 0) "正常" else "异常"}\n上次巡检: ${device.last_run_time}"
            edit.setOnClickListener {
                cancel()
                val bundle = Bundle()
                bundle.putString("id", device.id)
                bundle.putString("work_type", device.work_type)
                toStartActivity(DeviceAddKtActivity::class.java, bundle)
            }
            add.setOnClickListener {
                cancel()
                val bundle = Bundle()
                // bundle.putSerializable("device", device)
                MmkvUtil.putString("device", device.toJsonStr())
                toStartActivity(ReportKtActivity::class.java, bundle)
            }
            go.setOnClickListener {
                CircleDialog.Builder()
                    .setItems(nais) { view, position ->
                        when (nais[position].name) {
                            "高德地图" -> {
                                val g = BaseUtil.openGaoDeNavi(
                                    requireActivity(),
                                    0.0, 0.0, "",
                                    device.lat!!.toDouble(),
                                    device.lng!!.toDouble(),
                                    device.address
                                )
                                if (g) cancel()
                            }

                            "百度地图" -> {
//                                val g = BaseUtil.goBaiduMap(
//                                    requireActivity(),
//                                    device.lat!!.toDouble(),
//                                    device.lng!!.toDouble(),
//                                    device.address
//                                )
//                                if (g) cancel()
                                val g = BaseUtil.openBaiDuNavi(
                                    requireActivity(),
                                    0.0, 0.0, "",
                                    device.lat!!.toDouble(),
                                    device.lng!!.toDouble(),
                                    device.address
                                )
                                if (g) cancel()
                            }

                            "腾讯地图" -> {
                                val g = BaseUtil.openTencentMap(
                                    requireActivity(),
                                    0.0, 0.0, "",
                                    device.lat!!.toDouble(),
                                    device.lng!!.toDouble(),
                                    device.address
                                )
                                if (g) cancel()
                            }
                        }
                        true
                    }
                    .setNegative("取消", null)
                    .show(parentFragmentManager)
            }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    fun onEventMainThread(event: EventBusModel) {
        when (event.type) {
            EventBusConfig.UP_LAT -> if (mViewModel.checkId.isNotEmpty()) {
                mViewModel.addMap(
                    "",
                    "0",
                    mViewModel.checkId,
                    "2",
                    mViewModel.upLatLngs.toJsonStr()
                )
//                var coordinates: ArrayList<ArrayList<Double>> = arrayListOf()
//                upLatLngs.forEach {
//                    var d: ArrayList<Double> = arrayListOf(it.lng,it.lat)
//                    coordinates.add(d)
//                }
//                val lu = Lu()
//                val features = Lu.Features()
//                val geometry = Lu.Features.Geometry()
//                geometry.coordinates = coordinates
//                features.geometry = geometry
//                lu.features.add(features)
//                log_e("lu-----"+lu.toJsonStr())
            }

            else -> {}
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        EventBus.getDefault().unregister(this)
    }

    override fun onSelectTypeComplete(
        work_type: String,
        device_type: String,
        work_type_name: String
    ) {
        // mViewModel.selectType = type
        mViewModel.work_type = work_type
        mViewModel.device_type = device_type
//        var t = type.name0
//        if (!type.device_type_name.isNullOrBlank())
//            t = "$t,${type.device_type_name}"
        mViewBind.tvType.text = work_type_name
        showLoading()
        getDevice()
    }

    /**
     * 获取地图边框坐标
     */
    private fun getPoint() {
        val projection = mViewModel.aMap.projection // 获取地图投影对象
        val rightBottomPoint = Point(mViewBind.all.width, mViewBind.all.height)
        mViewModel.leftTopLatLng = projection.fromScreenLocation(Point(0, 0))
        mViewModel.rightBottomLatLng = projection.fromScreenLocation(rightBottomPoint) // 右下角经纬度
        getDevice()
    }

    override fun onSelectDistrictComplete(type: SelectType) {
        mViewModel.selectDistrict = type
        mViewModel.city = type.id1
        mViewModel.district = type.id2
        var s = ""
        if (type.name2.isNotEmpty())
            s = type.name2
        else if (type.name1.isNotEmpty())
            s = type.name1
        else if (type.name0.isNotEmpty())
            s = type.name0
        mViewBind.tvDistrict.text = s
        getDevice()
    }

    override fun onCameraChange(p0: CameraPosition?) {
        // 当地图开始滑动时，取消之前安排的任务（如果有）
        handler.removeCallbacksAndMessages(null)
    }

    override fun onCameraChangeFinish(p0: CameraPosition?) {
        // 地图滑动结束时，安排getPoint()在1秒后执行
        runnable = Runnable {
            // showLoading()
            getPoint()
        }
        handler.postDelayed(runnable!!, delayMillis)
    }

    override fun onDestroy() {
        super.onDestroy()
        handler.removeCallbacksAndMessages(null)
    }
}

